home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / opengl / xlib / zrgb_pup.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  16.2 KB  |  538 lines

  1. /*
  2.  * Copyright 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.  *   zrgbmenu.c:
  19.  *
  20.  *    OpenGL-Xlib doublebuffered-RGB, depth-buffering, pop-up menu examp
  21.  *
  22.  *              zrgbmenu is the openGL "after" version of the IrisGL
  23.  *              "before" program, ~4Dgifts/examples/grafix/zrgbmenu.c
  24.  * 
  25.  *  It further implements--either manually via LEFTMOUSE, or in an
  26.  *  "automatic" (i.e. animation) mode format--movement of the polygons 
  27.  *  via compound rotations to allow for continuous screen-oriented 
  28.  *  rotations (see orient(), spin(), and drawScene() below).  Horizontal
  29.  *  mouse movement rotates the polygons about the y-axis where right is 
  30.  *  positive and left is negative.  Vertical mouse movement rotates the
  31.  *  polygons about the x-axis where down is positive and up is negative.
  32.  *
  33.  *                                            ratman - 1989
  34.  *                                                     1994, ported to OpenGL
  35.  */
  36. #include <GL/glx.h>
  37. #include <GL/glu.h>
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <X11/Xlib.h>
  41. #include <X11/Xutil.h>
  42. #include <X11/keysym.h>
  43.  
  44. #include "pup.h"
  45.  
  46. #define TRUE            1
  47. #define FALSE           0
  48.  
  49. /* Modes the program can be in */
  50. #define NOTHING 0
  51. #define ORIENT  1
  52. #define SPIN    2
  53.  
  54. /* Values returned from popup menu */
  55. #define MANUAL    1
  56. #define AUTOMATIC 2
  57. #define EXIT      3
  58.  
  59.  
  60. Display *dpy;                                    /* The X server connection */
  61. Atom del_atom;                                   /* WM_DELETE_WINDOW atom   */
  62. Window glwin;                                    /* handle to the GL window */
  63. XEvent event;
  64.  
  65. /* function declarations */
  66.  
  67. static void openwindow(char *);
  68. static void resize_buffer(void);
  69. static void clean_exit(void);
  70. void initGL(void);
  71. void orient(void);
  72. void update_scene(void);
  73. void spin(void);
  74. void drawScene(void);
  75. void drawPolys(void);
  76.  
  77. static float objmat[16] = {
  78.          1.0, 0.0, 0.0, 0.0,
  79.          0.0, 1.0, 0.0, 0.0,
  80.          0.0, 0.0, 1.0, 0.0,
  81.          0.0, 0.0, 0.0, 1.0,
  82. };
  83.  
  84. int xsize, ysize;                        /* current size-of-window keepers */
  85. long buffermode;          /* flag tracks current window (single or double) */
  86. int xpos, ypos, oxpos, oypos;                /* old and new mouse position */
  87.  
  88. int mode = 0;
  89. int menu;
  90. int omx, mx, omy, my;                         /* old and new mouse position */
  91. float scrnaspect;                             /* aspect ratio value         */
  92.  
  93. main(argc, argv)
  94. int argc;
  95. char *argv[];
  96. {
  97.     int myExpose, myConfigure, myButtPress, myKeyPress;
  98.     int needToDraw = 0;                  /* don't set this to true until
  99.                                              we get our first Expose event */
  100.     long menuval;
  101.  
  102.  
  103.     myExpose = myConfigure = myButtPress = myKeyPress = FALSE;
  104.  
  105.     openwindow(argv[0]);
  106.  
  107.     initGL();                                          /* do GL init stuff */
  108.  
  109.     /*
  110.      * The event loop.
  111.      */
  112.     while (1) {         /* standard logic:  get event(s), process event(s) */
  113.  
  114.  
  115.         XEvent event;
  116.         KeySym keysym;
  117.         char buf[4];
  118.  
  119.     /* this "do while" loop does the `get events' half of the "get events,
  120.      *  process events" action of the infinite while.  this is to ensure
  121.      *  the event queue is always drained before the events that have come
  122.      *  in are processed.
  123.      */
  124.     while (XPending(dpy)) {
  125.  
  126.             XNextEvent(dpy, &event);
  127.             switch (event.type) {
  128.  
  129.             /* "Expose" events are sort of like "REDRAW" in gl-speak in
  130.              *  terms of when a window becomes visible, or a previously
  131.              *  invisible part becomes visible.
  132.              */
  133.                 case Expose:                        /* Exposures */
  134.                     needToDraw = myExpose = TRUE;
  135.                     break;
  136.  
  137.             /* "ConfigNotify" events are like "REDRAW" in terms of changes
  138.              *   to a window's size or position.
  139.              */
  140.                 case ConfigureNotify:                /* Resize GL manually */
  141.                     xsize = event.xconfigure.width;
  142.                     ysize = event.xconfigure.height;
  143.                     needToDraw = myConfigure = TRUE;
  144.                     break;
  145.  
  146.             /* Wait for "MotionNotify" events so the queue doesn't fill up
  147.              */
  148.                 case MotionNotify:
  149.                     myButtPress = TRUE;
  150.                     xpos = event.xmotion.x;
  151.                     ypos = event.xmotion.y;
  152.             if (mode == ORIENT) {
  153.             update_scene();
  154.             needToDraw=TRUE;
  155.             }
  156.                     mode = ORIENT;
  157.                     break;
  158.  
  159.             /* "ButtonPress" events hail from the ButtonPressMask feed to
  160.              *   XCreateWindow via XSetWindowAttributes' event_mask field
  161.              */
  162.                 case ButtonPress:
  163.             if (event.xbutton.button == Button3) { /* RIGHTMOUSE:  */
  164.                         menuval = dopup(menu);
  165.                         switch(menuval) {
  166.                         case MANUAL:
  167.                             mode = NOTHING;
  168.                             break;
  169.                         case AUTOMATIC:
  170.                             mode = SPIN;
  171.                             needToDraw = TRUE;
  172.                             break;
  173.                         case EXIT:
  174.                             clean_exit();
  175.                             break;
  176.                         default:
  177.                             break;
  178.                     }
  179.                 }
  180.  
  181.             /* Wait for "ButtonRelease" events so the queue doesn't fill up
  182.              *  the way it wud if the user sits on ButtonPresss.
  183.              */
  184.                 case ButtonRelease:
  185.                     if (event.xbutton.button == Button1)     /* LEFTMOUSE:  */
  186.                         mode = NOTHING;                   /* switch back to */
  187.                     break;                                /* "manual" mode  */
  188.                      
  189.             /* "ClientMessage" is generated if the WM itself is being
  190.              *  gunned down and sends an exit signal to any running prog.
  191.              */
  192.                 case ClientMessage:
  193.                     if (event.xclient.data.l[0] == del_atom)
  194.                         clean_exit();
  195.                     break;
  196.  
  197.             /* "KeyPress" events are those that would be generated before
  198.              *   whenever queueing up any KEYBD key via qdevice.
  199.              */
  200.                 case KeyPress:
  201.                    /* save out which unmodified key (i.e. the  key was
  202.                     *  not modified w/something like "Shift", "Ctrl",
  203.                     *  or "Alt") got pressed for use below.
  204.                     */
  205.                     XLookupString((XKeyEvent *)&event, buf, 4, &keysym, 0);
  206.                     myKeyPress = TRUE;
  207.                     break;
  208.  
  209.                 default:
  210.                     break;
  211.  
  212.             }  /* end switch (event.type) */
  213.  
  214.  
  215.     }
  216.  
  217.     /* On an "Expose" event, redraw the affected pop'd or de-iconized window
  218.      */
  219.         if (myExpose) {
  220.             resize_buffer();
  221.             myExpose = FALSE;               /* reset flag--queue now empty */
  222.         }
  223.  
  224.     /* On a "ConfigureNotify" event, the GL window has either been moved or
  225.      *  resized.  Respond accordingly and then redraw its contents.
  226.      */
  227.         if (myConfigure) {
  228.             oxpos = xpos;
  229.             oypos = ypos;
  230.             resize_buffer();
  231.             myConfigure = FALSE;            /* reset flag--queue now empty */
  232.         }
  233.  
  234.         if (needToDraw) {
  235.             if (mode == SPIN) {
  236.                 update_scene();
  237.                 drawScene();
  238.                 /*
  239.                  * Note: Don't reset needToDraw, so we keep on
  240.                  * spinning.
  241.                  */
  242.             } else {
  243.                 drawScene();
  244.                 needToDraw = FALSE;
  245.             }
  246.         }
  247.  
  248.         /* On a keypress of Esc key, exit program.
  249.          */
  250.         if (myKeyPress) {
  251.             if (keysym == XK_Escape)
  252.                 clean_exit();
  253.         }
  254.  
  255.         if (myButtPress) {
  256.             orient();
  257.             drawScene();
  258.             myButtPress = FALSE;
  259. /*
  260.             mode = NOTHING;
  261. */
  262.         }
  263.     }      /* end while(1) */
  264.  
  265. }      /* end main */
  266.  
  267.  
  268.  
  269.  
  270. static int attributeList[] = { GLX_RGBA,
  271.                                GLX_DOUBLEBUFFER,
  272.                                GLX_RED_SIZE, 1,
  273.                                GLX_GREEN_SIZE, 1,
  274.                                GLX_BLUE_SIZE, 1,
  275.                                GLX_DEPTH_SIZE, 1,
  276.                                None };
  277. static int attributeList2[] = { GLX_RGBA,
  278.                                GLX_RED_SIZE, 1,
  279.                                GLX_GREEN_SIZE, 1,
  280.                                GLX_BLUE_SIZE, 1,
  281.                                GLX_DEPTH_SIZE, 1,
  282.                                None };
  283.  
  284. static Bool WaitForNotify(Display *d, XEvent *e, char *arg) {
  285.     return (e->type == MapNotify) && (e->xmap.window == (Window)arg);
  286. }
  287.  
  288. /*  openwindow -
  289.  *     establish connection to X server, get screen info, specify the
  290.  *     attributes we want the WM to try to provide, and create the GL window
  291.  */
  292. static void openwindow(char *progname) {
  293.  
  294.     XVisualInfo *vi;
  295.     GLXContext cx;
  296.     Colormap cmap;
  297.     XSizeHints Winhints;                          /* used to fix window size */
  298.     XSetWindowAttributes swa;
  299.     int scrnnum;                               /* X screen number            */
  300.     int xorig, yorig;                          /* window (upper-left) origin */
  301.     long scrnwidth, scrnheight;
  302.  
  303.  
  304.  
  305.  
  306.    /* define window initial size */
  307.     xorig = 50;  yorig = 40;
  308.     xsize = 300; ysize = 240;
  309.  
  310.    /* Connect to the X server and get screen info */
  311.     if ((dpy = XOpenDisplay(NULL)) == NULL) {
  312.         fprintf(stderr, "%s: cannot connect to X server %s\n",
  313.                                  progname, XDisplayName(NULL));
  314.         exit(1);
  315.     }
  316.  
  317.     scrnnum = DefaultScreen(dpy);
  318.     scrnwidth = DisplayWidth(dpy, scrnnum);
  319.     scrnheight = DisplayHeight(dpy, scrnnum);
  320.  
  321.     /* Code to keep same aspec ratio as the screen */
  322.     scrnaspect = ((float)scrnwidth)/((float)scrnheight);
  323.  
  324.         /* get an appropriate visual */
  325.     vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList);
  326.     if (vi == NULL) {
  327.         fprintf(stderr, "Unable to obtain Doublebuffered visual;  ");
  328.         fprintf(stderr, "now going for singlebuffer'd...\n");
  329.         vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList2);
  330.     }
  331.     if (vi == NULL) {
  332.         printf("Unable to obtain Singlebuffered VISUAL(????)\n");
  333.         exit(0);
  334.     }
  335.  
  336.     /* create GLX context */
  337.     cx = glXCreateContext(dpy, vi, None, GL_TRUE);
  338.  
  339.     /* create a colormap */
  340.     cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen),
  341.                            vi->visual, AllocNone);
  342.  
  343.     /* create a window */
  344.     swa.colormap = cmap;
  345.     swa.border_pixel = 0;
  346.     swa.event_mask = StructureNotifyMask  | ButtonPressMask | ButtonReleaseMask
  347.                         | ExposureMask | Button1MotionMask | KeyPressMask;  
  348.     glwin = XCreateWindow(dpy, RootWindow(dpy, vi->screen),
  349.                           xorig, yorig, xsize, ysize,
  350.                           0, vi->depth, InputOutput, vi->visual,
  351.                           CWBorderPixel|CWColormap|CWEventMask, &swa);
  352.  
  353.     XMapWindow(dpy, glwin);
  354.     XIfEvent(dpy, &event, WaitForNotify, (char*)glwin);
  355.  
  356.     /* connect the context to the window */
  357.     glXMakeCurrent(dpy, glwin, cx);
  358.  
  359.     if (!(glwin)) {
  360.         fprintf(stderr,"%s: couldn't create \"parent\" X window\n",progname);
  361.         exit(1);
  362.     }
  363.  
  364.    /* define string that will show up in the window title bar (and icon) */
  365.     XStoreName(dpy, glwin, "rgb depth/dbl -buffered pop-up menu prog");
  366.  
  367.  
  368.    /* specify the values for the Window Size Hints we want to enforce:  this
  369.     *  window's aspect ratio needs to stay at 1:1, constrain min and max
  370.     *  window size, and specify the initial size of the window.
  371.     */
  372.     Winhints.width  = xsize;          /* specify desired x/y size of window */
  373.     Winhints.height = ysize;
  374.     Winhints.min_width = xorig;                       /* define min and max */
  375.     Winhints.max_width = scrnheight-1;                /* width and height   */
  376.     Winhints.min_height = yorig;
  377.     Winhints.max_height = scrnheight-1;
  378.     Winhints.min_aspect.x = scrnwidth;/* keep aspect to a scrnX:scrnY ratio */
  379.     Winhints.max_aspect.x = scrnwidth;
  380.     Winhints.min_aspect.y = scrnheight;
  381.     Winhints.max_aspect.y = scrnheight;
  382.     Winhints.flags = USSize|PMaxSize|PMinSize|PAspect;           /* set the */
  383.     XSetNormalHints(dpy, glwin, &Winhints);      /* corresponding flags */
  384.  
  385.    /* express interest in WM killing this app */
  386.     if ((del_atom = XInternAtom(dpy, "WM_DELETE_WINDOW", True)) != None)
  387.         XSetWMProtocols(dpy, glwin, &del_atom, 1);
  388.  
  389.     menu = defpup(dpy, scrnnum, 
  390.           "OGL RGB depth-bufr'd pup prog %t|Manual Mode|Automatic Mode|Exit");
  391.     return ;
  392. }
  393.  
  394.  
  395.  
  396. /*  window has been moved or resized so update viewport & CTM stuff.
  397.  */
  398. static void resize_buffer() {
  399.     scrnaspect = xsize / (double) ysize;
  400.     glViewport(0, 0, xsize-1, ysize-1);
  401. }
  402.  
  403.  
  404.  
  405. /*  clean up before exiting
  406.  */
  407. static void clean_exit(void)
  408. {
  409.     XCloseDisplay(dpy);
  410.     exit(0);
  411. }
  412.  
  413.  
  414.  
  415. /* setup all necessary GL initialzation parameters.
  416.  */
  417. void initGL(void)
  418. {
  419.     glEnable(GL_DEPTH_TEST);
  420.     glClearColor(0.16, 0.39, 0.78, 0.0);
  421.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  422.     glLoadIdentity();
  423.     gluPerspective(400.0, scrnaspect, 30.0, 600.0);
  424. }
  425.  
  426.  
  427.  
  428. void update_scene(void) {
  429.  
  430.     switch (mode) {
  431.  
  432.         case ORIENT:
  433.             orient();
  434.             break;
  435.         case SPIN:
  436.             spin();
  437.             break;
  438.     }
  439. }
  440.  
  441.  
  442. void orient(void)
  443. {
  444.     float dx, dy;
  445.  
  446.     glPushMatrix();
  447.     dx = 0.01 * (xpos-oxpos);
  448.     dy = 0.01 * (oypos-ypos);
  449.     glLoadIdentity();
  450.     glRotatef(dx, 1.0, 0.0, 0.0);
  451.     glRotatef(dy, 0.0, 1.0, 0.0);
  452.     glMultMatrixf(objmat);
  453.     glGetFloatv(GL_MODELVIEW_MATRIX, objmat);
  454.  
  455.     glPopMatrix();
  456. }
  457.  
  458.  
  459.  
  460. void spin (void) {
  461.  
  462.     glPushMatrix();
  463.  
  464.     glLoadIdentity();
  465.  
  466.     glRotatef(2.5, 1.0, 0.0, 0.0);            
  467.     glRotatef(3.0, 0.0, 1.0, 0.0);           
  468.     glRotatef(2.0, 0.0, 0.0, 1.0);          
  469.  
  470.     glMultMatrixf(objmat);
  471.     glGetFloatv(GL_MODELVIEW_MATRIX, objmat);
  472.  
  473.     glPopMatrix();
  474.  
  475. }
  476.  
  477.  
  478. void drawScene(void)
  479. {
  480.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  481.  
  482.     glLoadIdentity();
  483.     gluPerspective(400.0, scrnaspect, 30.0, 600.0);
  484.     glTranslatef(0.0, 0.0, -40.0);
  485.     glMultMatrixf(objmat);
  486.     glRotatef(-400.0, 0.0, 1.0, 0.0); /* skews orig view to show all polys */
  487.     drawPolys();
  488.     glXSwapBuffers(dpy, glwin);
  489. }
  490.  
  491.  
  492.  
  493. float polygon1[3][3] = { {-10.0, -10.0,   0.0,},
  494.                          { 10.0, -10.0,   0.0,},
  495.                          {-10.0,  10.0,   0.0,} };
  496.  
  497. float polygon2[3][3] = { {  0.0, -10.0, -10.0,},
  498.                          {  0.0, -10.0,  10.0,},
  499.                          {  0.0,   5.0, -10.0,} };
  500.  
  501. float polygon3[4][3] = { {-10.0,   6.0,   4.0,},
  502.                          {-10.0,   3.0,   4.0,},
  503.                          {  4.0,  -9.0, -10.0,},
  504.                          {  4.0,  -6.0, -10.0,} };
  505.  
  506. void drawPolys(void) {
  507.  
  508.     glBegin(GL_POLYGON);
  509.     glColor4f(0.0, 0.0, 0.0, 0.0);
  510.     glVertex3fv(&polygon1[0][0]);
  511.     glColor4f(0.5, 0.5, 0.5, 0.0);
  512.     glVertex3fv(&polygon1[1][0]);
  513.     glColor4f(1.0, 1.0, 1.0, 0.0);
  514.     glVertex3fv(&polygon1[2][0]);
  515.     glEnd();
  516.  
  517.     glBegin(GL_POLYGON);
  518.     glColor4f(1.0, 1.0, 0.0, 0.0);
  519.     glVertex3fv(&polygon2[0][0]);
  520.     glColor4f(0.0, 1.0, 0.5, 0.0);
  521.     glVertex3fv(&polygon2[1][0]);
  522.     glColor4f(0.0, 0.0, 1.0, 0.0);
  523.     glVertex3fv(&polygon2[2][0]);
  524.     glEnd();
  525.  
  526.     glBegin(GL_POLYGON);
  527.     glColor4f(1.0, 1.0, 0.0, 0.0);
  528.     glVertex3fv(&polygon3[0][0]);
  529.     glColor4f(1.0, 0.0, 1.0, 0.0);
  530.     glVertex3fv(&polygon3[1][0]);
  531.     glColor4f(0.0, 0.0, 1.0, 0.0);
  532.     glVertex3fv(&polygon3[2][0]);
  533.     glColor4f(1.0, 0.0, 1.0, 0.0);
  534.     glVertex3fv(&polygon3[3][0]);
  535.     glEnd();
  536.  
  537. }
  538.